//package cn.maiyar.web;
//
//import cn.hutool.core.util.StrUtil;
//import com.fasterxml.jackson.databind.exc.MismatchedInputException;
//import cn.maiyar.common.api.BusinessException;
//import cn.maiyar.common.api.R;
//import cn.maiyar.common.api.ResultCode;
//import cn.maiyar.common.api.ServiceException;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.context.MessageSource;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.i18n.LocaleContextHolder;
//import org.springframework.http.converter.HttpMessageConversionException;
//import org.springframework.http.converter.HttpMessageNotReadableException;
//import org.springframework.validation.ObjectError;
//import org.springframework.web.HttpMediaTypeNotSupportedException;
//import org.springframework.web.HttpRequestMethodNotSupportedException;
//import org.springframework.web.bind.MethodArgumentNotValidException;
//import org.springframework.web.bind.MissingServletRequestParameterException;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//import org.springframework.web.bind.annotation.RestControllerAdvice;
//import org.springframework.web.client.RestClientException;
//import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
//import org.springframework.web.servlet.NoHandlerFoundException;
//
//import javax.annotation.Resource;
//import javax.validation.ConstraintViolation;
//import javax.validation.ConstraintViolationException;
//import java.nio.file.AccessDeniedException;
//import java.sql.SQLException;
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * 全局异常处理
// *
// * @author c.c
// */
//@Slf4j
//@Configuration
//@RestControllerAdvice
//public class ControllerExceptionHandler {
//
//    @Resource
//    private MessageSource messageSource;
//
//    /**
//     * 内部接口服务异常统一处理方法
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {ServiceException.class})
//    public R serviceException(ServiceException e) {
//        log.error("内部服务异常:", e);
//        return R.fail(e.getResultCode(), this.getMessages(e.getMessage()));
//    }
//
//    /**
//     * 外部接口业务异常统一处理方法
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {BusinessException.class})
//    public R businessException(BusinessException e) {
//        log.error("外部业务异常:", e);
//        return R.fail(e.getResultCode(), this.getMessages(e.getMessage()));
//    }
//
//    /**
//     * 缺少必要的请求参数
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler({MissingServletRequestParameterException.class})
//    public R processRequestParameterException(MissingServletRequestParameterException e) {
//        log.error("缺少必要参数异常:", e);
//        return R.fail(ResultCode.PARAM_MISS, e.getParameterName() + " is null!");
//    }
//
//    /**
//     * 拦截未知的运行时异常
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {RuntimeException.class})
//    public R runtimeException(RuntimeException e) {
//        log.error("运行时异常:", e);
//        Throwable cause = e.getCause();
//        String message = e.getMessage();
//        ResultCode failure = ResultCode.FAILURE;
//        if (cause instanceof IllegalArgumentException) {
//            failure = ResultCode.METHOD_NOT_SUPPORTED;
//            message = StrUtil.isNotEmpty(message) ? message : getMessages(String.valueOf(ResultCode.FAILURE.getCode()));
//        } else if (cause instanceof AccessDeniedException || cause instanceof HttpMessageNotReadableException || cause instanceof RestClientException) {
//            failure = ResultCode.REQ_REJECT;
//            message = StrUtil.isNotEmpty(message) ? message : getMessages(String.valueOf(ResultCode.REQ_REJECT.getCode()));
//        } else {
//            message = StrUtil.isNotEmpty(message) ? message : getMessages(String.valueOf(ResultCode.FAILURE.getCode()));
//        }
//        return R.fail(failure, message);
//    }
//
//    /**
//     * 所有异常统一处理
//     * 返回状态码:500
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {Exception.class})
//    public R exception(Exception e) {
//        log.error("未知异常:", e);
//        String message = e.getMessage();
//        ResultCode failure = ResultCode.INTERNAL_SERVER_ERROR;
//        if (e instanceof NoHandlerFoundException) {
//            failure = ResultCode.NOT_FOUND;
//            message = StrUtil.isNotEmpty(message) ? message : getMessages(String.valueOf(ResultCode.NOT_FOUND.getCode()));
//        } else if (e instanceof MismatchedInputException) {
//            failure = ResultCode.IO_ERROR;
//            message = StrUtil.isNotEmpty(message) ? message : getMessages(String.valueOf(ResultCode.IO_ERROR.getCode()));
//        } else {
//            message = StrUtil.isNotEmpty(message) ? message : getMessages(String.valueOf(ResultCode.FAILURE.getCode()));
//        }
//        return R.fail(failure, message);
//    }
//
//    /**
//     * 不支持当前请求方法
//     * 返回状态码:405
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {HttpRequestMethodNotSupportedException.class})
//    public R handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
//        log.error("不支持当前媒体类型:", e);
//        return R.fail(ResultCode.METHOD_NOT_SUPPORTED);
//    }
//
//    /**
//     * 不支持当前媒体类型
//     * 返回状态码:415
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {HttpMediaTypeNotSupportedException.class})
//    public R handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
//        log.error("不支持当前媒体类型:", e);
//        return R.fail(ResultCode.MEDIA_TYPE_NOT_SUPPORTED);
//    }
//
//    /**
//     * SQLException sql异常处理
//     * 返回状态码:500
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {SQLException.class})
//    public R handlesqlexception(SQLException e) {
//        log.error("数据库异常:", e);
//        return R.fail(ResultCode.DATASOURCE_ERROR);
//    }
//
//    /**
//     * 字段校验返回处理
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = MethodArgumentNotValidException.class)
//    public R methodArgumentNotValidHandler(MethodArgumentNotValidException e) {
//        log.error("字段校验返回处理:", e);
//        List<String> defaultMessages = e.getBindingResult().getAllErrors()
//                .stream()
//                .map(ObjectError::getDefaultMessage)
//                .collect(Collectors.toList());
//        return R.fail(ResultCode.PARAM_VALID_ERROR, getMessages(defaultMessages.toString()));
//    }
//
//    /**
//     * 字段校验返回处理
//     * GET @RequestParam @PathVariable等
//     *
//     * @param e
//     * @return
//     */
//    @ExceptionHandler(value = {ConstraintViolationException.class})
//    public R constraintViolationException(ConstraintViolationException e) {
//        log.error("字段校验返回处理:", e);
//        List<String> errorInformation = e.getConstraintViolations()
//                .stream()
//                .map(ConstraintViolation::getMessage)
//                .collect(Collectors.toList());
//        return R.fail(ResultCode.PARAM_VALID_ERROR, getMessages(errorInformation.toString()));
//    }
//
//    /**
//     * 参数类型转换错误
//     *
//     * @param e 错误
//     * @return 错误信息
//     */
//    @ExceptionHandler(value = {HttpMessageConversionException.class})
//    public R httpMessageConversionException(HttpMessageConversionException e) {
//        log.error("请求参数类型错误:", e);
//        return R.fail(ResultCode.PARAM_TYPE_ERROR);
//    }
//
//    /**
//     * 参数类型转换错误
//     *
//     * @param e 错误
//     * @return 错误信息
//     */
//    @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class})
//    public R httpMessageConversionException(MethodArgumentTypeMismatchException e) {
//        log.error("参数类型不匹配:", e);
//        return R.fail(ResultCode.PARAM_TYPE_ERROR);
//    }
//
//    /**
//     * 获取对应的语言消息
//     *
//     * @param message
//     * @return
//     */
//    private String getMessages(String message) {
//        if (StrUtil.isBlank(message)) {
//            return message;
//        }
//        String code = message.replace("[", "").replace("]", "");
//        return messageSource.getMessage(code, new Object[]{}, code, LocaleContextHolder.getLocale());
//    }
//}
